//using System;
//using System.IO;
//using System.Threading;
//using System.Collections.Generic;
//using System.Text;

//using Weazel.Gezel.Model;
//using Weazel.Gezel.Model.Errors;

//using Weazel.Toad.Application.Items;

//using Weazel.Microblaze.Elf;
//using Weazel.Microblaze.Simulator.Components;
//using Weazel.Microblaze.Simulator.Engine;

//namespace Weazel.Toad.Application
//{
//  public class MicroblazeCosimulation
//  { 
//    /// <summary>
//    /// Raised when a simulation is started
//    /// </summary>
//    public event EventHandler<SimulationEventArgs> SimulationStarted;

//    /// <summary>
//    /// Raised when a running simulation has text to be written to the console
//    /// or other similar device
//    /// </summary>
//    public event EventHandler<SimulationOutputReadyEventArgs> SimulationOutputReady;

//    /// <summary>
//    /// Raised when a simulation ends
//    /// </summary>
//    public event EventHandler<SimulationEventArgs> SimulationDone;

//    /// <summary>
//    /// the (gezel) output of the last or a current simulation
//    /// </summary>
//    private StringBuilder outputBuffer = new StringBuilder();
//    public StringBuilder OutputBuffer
//    {
//      get
//      {
//        return outputBuffer;
//      }
//    }

//    private GezelSimulationOutputWriter outputWriter =
//      new GezelSimulationOutputWriter();

//    private bool isRunning = false;

//    // the gezel file used by the co-simulation (toad)
//    private Items.GezelTextFile gezelFile;

//    // the gezel model used by the co-simulation
//    private Model gezelModel;

//    // the elf file used by the co-simulation
//    private ElfFile elfFile;

//    // the microblaze simulator object
//    private Simulator simulator;

//    private MicroblazeCosimulationSettings settings;
//    public MicroblazeCosimulationSettings Settings
//    {
//      get { return settings; }
//      set { settings = value; }
//    }

//    private Thread runThread;
//    private bool run = false;
//    private bool runToAddressEnabled;
//    private uint runToAddress;
//    private bool updateEnabled = true;
//    private delegate void UpdateViewDelegate();

//    private AutoResetEvent simulationStopped = new AutoResetEvent(false);

//    private delegate void outputReadyDelegate(string text);
//    private delegate void simulationStartedDelegate();
//    private delegate void simulationDoneDelegate();

//    void raiseSimulationStarted()
//    {
//      if (SimulationStarted != null)
//        SimulationStarted(this, new SimulationEventArgs(gezelFile));
//    }

//    void raiseSimulationDone()
//    {
//      // clean up ..
//      simulator.Core.MemorySpace.CleanUp();

//      if (SimulationDone != null)
//        SimulationDone(this, new SimulationEventArgs(gezelFile));
//    }

//    void raiseOutputReadyEvent(string text)
//    {
//      if (SimulationOutputReady != null)
//        SimulationOutputReady(this, new SimulationOutputReadyEventArgs(text));
//    }

//    void outputWriter_OutputReadyEvent(string text)
//    {
//      if (text == "")
//        return;

//      // Running multiple simulations will cause the main thread to be monopolized by
//      // serving the event handler handling the 'ReportProgress' event - this delay 
//      // makes sure this does not happen.

//      System.Threading.Thread.Sleep(10);

//      // raise event on main thread
//      Application.Instance.MainForm.Invoke(
//        new outputReadyDelegate(raiseOutputReadyEvent), new object[] { text }
//      );
//    }

//    public MicroblazeCosimulation()
//    {
//      this.outputWriter.OutputReadyEvent +=  
//                new GezelSimulationOutputWriter.OutputReadyEventHandler(outputWriter_OutputReadyEvent);
//    }

//    /// <summary>
//    /// Show a form the user can use to setup the simulation
//    /// </summary>
//    /// <returns>true if the simulation was configured</returns>
//    public bool Setup()
//    {
//      Forms.SetupMicroblazeSimulationForm form =
//        new Weazel.Toad.Application.Forms.SetupMicroblazeSimulationForm();

//      form.Settings = settings;

//      if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
//      {
//        this.settings = form.Settings;
//        return true;
//      }

//      return false;
//    }


//    public void RunToAddress(uint address)
//    {
//      runToAddress = address;
//      runToAddressEnabled = true;

//      Run();
//    }

//    /// <summary>
//    /// Starting running the simulation. Simulation will stop when
//    /// the "stop" flag has been set.
//    /// </summary>
//    public void Run()
//    {
//      if (isRunning)
//        return;

//      if (!Initialize())
//        return;

//      string mbOutputWindowName = "Microblaze UART output";
//      string mbOpbOperationsWindowName = "Microblaze/Gezel Operations";

//      if (!Application.Instance.MainForm.LayoutControl.ContainerPanel.ConsoleOutputControlExists(mbOutputWindowName))
//        Application.Instance.MainForm.LayoutControl.ContainerPanel.CreateConsoleOutputControl(mbOutputWindowName);
//      else
//        Application.Instance.MainForm.LayoutControl.ContainerPanel.GetConsoleOutputControl(mbOutputWindowName).Clear();

//      if (!Application.Instance.MainForm.LayoutControl.ContainerPanel.ConsoleOutputControlExists(mbOpbOperationsWindowName))
//        Application.Instance.MainForm.LayoutControl.ContainerPanel.CreateConsoleOutputControl(mbOpbOperationsWindowName);
//      else
//        Application.Instance.MainForm.LayoutControl.ContainerPanel.GetConsoleOutputControl(mbOpbOperationsWindowName).Clear();

//      simulator.ConsoleOutputWriter =
//        new Controls.ConsoleOutputTextBoxWriter(
//        Application.Instance.MainForm.LayoutControl.ContainerPanel.GetConsoleOutputControl(mbOutputWindowName)
//      );

//      simulator.OpbIpifOutputWriter =
//        new Controls.ConsoleOutputTextBoxWriter(
//        Application.Instance.MainForm.LayoutControl.ContainerPanel.GetConsoleOutputControl(mbOpbOperationsWindowName)
//      );

//      // switch to output ..
//      Application.Instance.MainForm.LayoutControl.ContainerPanel.SetCurrentPage(mbOutputWindowName);

//      // clear any existing output
//      Application.Instance.MainForm.LayoutControl.ContainerPanel.GetConsoleOutputControl(mbOutputWindowName).Clear();

//      Forms.ProgressForm.CloseOpenForm();

//      runThread = new Thread(new ThreadStart(runThreadBody));
//      runThread.Start();
//    }

//    public bool Initialize()
//    {
//      if (settings == null)
//      {
//        // ask the user to setup the simulation first ..
//        if (!Setup())
//          return false;
//      }

//      Forms.ProgressForm.Show("Launching Co-simulation ..");
            
//      // read and process the ELF file
//      Forms.ProgressForm.UpdateProgress("Processing Elf file");
      
//      elfFile = ElfFile.OpenAndProcessFile(settings.LastProgramImageName);

//      // parse and verify gezel model
//      if (Application.Instance.SelectedItem is Items.GezelTextFile)
//      {
//        Forms.ProgressForm.UpdateProgress("Parsing and verifying Gezel model");

//        Items.GezelTextFile gezelFile =
//          Application.Instance.SelectedItem as Items.GezelTextFile;

//        List<VerificationError> verificationErrors = new List<VerificationError>();
//        List<VerificationWarning> warnings = new List<VerificationWarning>();
//        List<ParseError> parseErrors = new List<ParseError>();

//        Model model = 
//          gezelFile.ParseAndVerifyModel(
//            ref parseErrors, 
//            ref verificationErrors, 
//            ref warnings
//          );
        
//        if (verificationErrors.Count != 0 || parseErrors.Count != 0)
//        {
//          Forms.ProgressForm.CloseOpenForm();
//          string message = "Model contains errors - simulation aborted";
//          System.Windows.Forms.MessageBox.Show(message);
//          return false;
//        }

//        this.gezelModel = model;
//      }

//      // create the simulation object
//      simulator =
//        new Simulator(settings.PlatformDescription, elfFile);

//      simulator.ProgressEvent +=
//        new EventHandler<ProgressEventArgs>(simulator_ProgressEvent);

//      simulator.GezelModel = gezelModel;

//      // initialize the sim (progress reported by "ProgressEvent")
//      if (!simulator.Initialize())
//      {
//        Forms.ProgressForm.CloseOpenForm();
//        return false;
//      }

//      // register a custom event handler. This handler will raise a second event
//      if(simulator.GezelSimulation != null)
//        simulator.GezelSimulation.OutputWriter = outputWriter;

//      return true;
//    }

//    void simulator_ProgressEvent(object sender, ProgressEventArgs e)
//    {
//      Forms.ProgressForm.UpdateProgress(e.Text);
//    }

//    public void Stop()
//    {
//      if (!isRunning)
//        return;
      
//      // signal run thread to stop 
//      run = false;
//      runToAddressEnabled = false;

//      // make it crash
//      runThread.Abort();            
//    }

//    public void StepSimulation()
//    {
//      simulator.Step();

//      if (updateEnabled)
//      {
//       // form.MemoryView.UpdateMemoryView();
//       // form.RegisterView.UpdateContent();

//        // set the disassembly view to the current instruction
//       // form.DisassemblyView.ScrollToInstructionAtAddress(simulator.Core.Pc);
//       // setNextInstruction(simulator.Core.Pc);
//      }
//    }



//    private void runThreadBody()
//    {
//      run = true;
//      updateEnabled = false;
//      isRunning = true;

//      Application.Instance.MainForm.Invoke(new simulationStartedDelegate(raiseSimulationStarted));

//      try
//      {
//        while (run)
//        {
//          StepSimulation();

//          if (runToAddressEnabled && simulator.Core.Pc == runToAddress)
//          {
//            run = false;
//            // runThread.Abort();
//          }
//        }
//      }
//      catch (MemoryException e)
//      {
//        System.Windows.Forms.MessageBox.Show(e.Message, "Simulation Aborted");
//      }
//      catch (ThreadAbortException)
//      {
//        // properly stopped ..

//        // note: code duplication is needed -> execution will not continue after handling
//        // the thread abort exception

//        updateEnabled = true;
//        runToAddressEnabled = false;
//        isRunning = false;

//        Application.Instance.MainForm.Invoke(new simulationDoneDelegate(raiseSimulationDone));
//      }
//      catch (Exception e)
//      {
//        System.Windows.Forms.MessageBox.Show(e.Message, "Simulation aborted");
//      }

//      updateEnabled = true;
//      runToAddressEnabled = false;
//      isRunning = false;

//      Application.Instance.MainForm.Invoke(new simulationDoneDelegate(raiseSimulationDone));
//    }

//    private void updateViewAfterRunDelegate()
//    {
//      //// disable stop and re-enable run and run-to
//      //Commands.Command.GetCommand(typeof(Commands.StopSimulationCommand)).Enabled = false;
//      //Commands.Command.GetCommand(typeof(Commands.RunSimulationCommand)).Enabled = true;
//      //Commands.Command.GetCommand(typeof(Commands.RunToSimulationCommand)).Enabled = true;

//      //form.MemoryView.UpdateMemoryView();
//      //form.RegisterView.UpdateContent();
//      //simulator_SimulationStateChanged(this, EventArgs.Empty);
//      //setNextInstruction(simulator.Core.Pc);
//    }
//  }
//}
